// 日志工具

import { Logger } from '../types';

export enum LogLevel {
  DEBUG = 0,
  INFO = 1,
  WARN = 2,
  ERROR = 3,
}

export interface LogEntry {
  level: LogLevel;
  message: string;
  timestamp: Date;
  meta?: any;
  context?: string;
}

export class DefaultLogger implements Logger {
  private level: LogLevel;
  private context: string | undefined;

  constructor(level: LogLevel = LogLevel.INFO, context?: string) {
    this.level = level;
    this.context = context;
  }

  debug(message: string, meta?: any): void {
    this.log(LogLevel.DEBUG, message, meta);
  }

  info(message: string, meta?: any): void {
    this.log(LogLevel.INFO, message, meta);
  }

  warn(message: string, meta?: any): void {
    this.log(LogLevel.WARN, message, meta);
  }

  error(message: string, meta?: any): void {
    this.log(LogLevel.ERROR, message, meta);
  }

  private log(level: LogLevel, message: string, meta?: any): void {
    if (level < this.level) {
      return;
    }

    const entry: LogEntry = {
      level,
      message,
      timestamp: new Date(),
      meta,
      ...(this.context && { context: this.context }),
    };

    this.output(entry);
  }

  private output(entry: LogEntry): void {
    const levelName = LogLevel[entry.level];
    const timestamp = entry.timestamp.toISOString();
    const context = entry.context ? `[${entry.context}]` : '';
    const meta = entry.meta ? ` ${JSON.stringify(entry.meta)}` : '';

    const logMessage = `${timestamp} ${levelName} ${context} ${entry.message}${meta}`;

    switch (entry.level) {
      case LogLevel.DEBUG:
        console.debug(logMessage);
        break;
      case LogLevel.INFO:
        console.info(logMessage);
        break;
      case LogLevel.WARN:
        console.warn(logMessage);
        break;
      case LogLevel.ERROR:
        console.error(logMessage);
        break;
    }
  }

  createChild(context: string): Logger {
    const childContext = this.context ? `${this.context}:${context}` : context;
    return new DefaultLogger(this.level, childContext);
  }
}

// 空日志器 - 用于禁用日志
export class NullLogger implements Logger {
  debug(): void {}
  info(): void {}
  warn(): void {}
  error(): void {}
}

// 内存日志器 - 用于测试
export class MemoryLogger implements Logger {
  private logs: LogEntry[] = [];

  debug(message: string, meta?: any): void {
    this.addLog(LogLevel.DEBUG, message, meta);
  }

  info(message: string, meta?: any): void {
    this.addLog(LogLevel.INFO, message, meta);
  }

  warn(message: string, meta?: any): void {
    this.addLog(LogLevel.WARN, message, meta);
  }

  error(message: string, meta?: any): void {
    this.addLog(LogLevel.ERROR, message, meta);
  }

  private addLog(level: LogLevel, message: string, meta?: any): void {
    this.logs.push({
      level,
      message,
      timestamp: new Date(),
      meta,
    });
  }

  getLogs(): LogEntry[] {
    return [...this.logs];
  }

  getLogsByLevel(level: LogLevel): LogEntry[] {
    return this.logs.filter(log => log.level === level);
  }

  clear(): void {
    this.logs = [];
  }

  getLogCount(): number {
    return this.logs.length;
  }
}

// 默认日志器实例
export const defaultLogger = new DefaultLogger(LogLevel.INFO, 'RedisToolkit');

// 创建日志器工厂
export function createLogger(level: LogLevel = LogLevel.INFO, context?: string): Logger {
  return new DefaultLogger(level, context);
}

// 日志级别解析
export function parseLogLevel(level: string): LogLevel {
  switch (level.toLowerCase()) {
    case 'debug':
      return LogLevel.DEBUG;
    case 'info':
      return LogLevel.INFO;
    case 'warn':
    case 'warning':
      return LogLevel.WARN;
    case 'error':
      return LogLevel.ERROR;
    default:
      return LogLevel.INFO;
  }
}
